<?php
if (!defined('__COLA_DIR__')) exit;
/**
 * 内容基类
 *
 * @author edikud
 * @package Widget
 * @copyright Copyright (c) 2019 Cola (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */

class Widget_Abstract_Contents extends Widget
{
    /**
     * 取出mid
     *
     * @access protected
     * @return integer
     */
    protected function ___mid()
    {
		$mids = explode(',', $this->mids);
        return $mids[0];
    }

    /**
     * 将tags取出
     *
     * @access protected
     * @return array
     */
    protected function ___tags()
    {
	    $taglist = $this->have() ? Json::decode($this->tagsJson) : '';
	    $tags = [];

	    if($taglist) {
		    foreach($taglist as $tagID => $tag)
			{
			    $tags[$tagID] = array('name'=>$tag['name'], 'permalink'=> Router::url('tag', array('alias' => $tag['alias']), $this->options->index));
		    }
	    }
        return $tags;
    }

    /**
     * 文章作者
     *
     * @access protected
     * @return Container
     */
    protected function ___author()
    {
        return $this->widget('Widget_Users_List@' . $this->uid, 
		    array('uid' => $this->uid, 'limit' => 1));
    }

    /**
     * 获取词义化日期
     *
     * @access protected
     * @return string
     */
    protected function ___dateWord()
    {
        return $this->date->word();
    }

    /**
     * 对文章的简短纯文本描述
     *
     * @access protected
     * @return string
     */
    protected function ___description()
    {
        $plainTxt = str_replace("\n", '', trim(strip_tags($this->intro)));
        $plainTxt = $plainTxt ? $plainTxt : $this->title;
        return Common::subStr($plainTxt, 0, 100, '...');
    }

    /**
     * 获取文章内容
     *
     * @access protected
     * @return string
     */
    protected function ___content()
    {
		$content = $this->text;
		
		/** 插件接口 */
		//HOOK $content | PLUG_Abstract_Contents_Text($content, $this);

		return $content;
    }

    /**
     * 锚点id
     *
     * @access protected
     * @return string
     */
    protected function ___theId()
    {
        return $this->type . '-' . $this->cid;
    }
    
    /**
     * 回复框id
     * 
     * @access protected
     * @return string
     */
    protected function ___respondId()
    {
        return 'respond-' . $this->theId;
    }
    
    /**
     * 评论地址
     * 
     * @access protected
     * @return string
     */
    protected function ___commentUrl()
    {
        /** 生成反馈地址 */
        /** 评论 */
        return Router::url('feedback',
            array('permalink' => $this->pathinfo), $this->options->index);
    }
    
    /**
     * 回复地址
     * 
     * @access protected
     * @return string
     */
    protected function ___responseUrl()
    {
        return $this->permalink . '#' . $this->respondId;
    }
	
    /**
     * 获取页面偏移
     *
     * @access protected
     * @param string $column 字段名
     * @param integer $offset 偏移值
     * @param string $type 类型
     * @param integer $uid 作者
     * @param integer $pageSize 分页值
     * @return integer
     */
    protected function getPageOffset($column, $offset, $type, $uid = 0, $pageSize = 20)
    {
        $select = $this->db->select(array('COUNT(table.contents.cid)' => 'num'))
		    ->from('table.contents')
            ->where("table.contents.{$column} > {$offset}")
            ->where("table.contents.type = ?", $type);

        if ($uid > 0) {
            $select->where('table.contents.uid = ?', $uid);
        }
		
		$count = $select->fetchObject()->num + 1;
        return ceil($count / $pageSize);
    }

    /**
     * 获取查询对象
     *
     * @access public
     * @return Db_Query
     */
    public function select()
    {
        return $this->db->select()
		    ->from('table.contents');
    }
	
    /**
     * 插入内容
     *
     * @access public
     * @param array $values 内容结构数组
     * @return integer
     */
    public function insert(array $values)
    {
        /** 构建插入结构 */
        $content = array(
			'mids'          =>  empty($values['mids']) ? '' : $values['mids'],
			'title'         =>  empty($values['title']) ? '' : htmlspecialchars($values['title']),
			'uid'           =>  isset($values['uid']) ? intval($values['uid']) : $this->user->uid,
			/** 避免冲突 */
			'alias'         =>  Common::aliasName(),
            'type'          =>  empty($values['type']) ? 'post' : $values['type'],
            'intro'         =>  empty($values['intro']) ? '' : $values['intro'],
			'pic'           =>  empty($values['pic']) ? '' : $values['pic'],
			'template'      =>  empty($values['template']) ? '' : $values['template'],
            'text'          =>  empty($values['text']) ? '' : $this->filterText($values['text']),
            'created'       =>  empty($values['created']) ? $this->options->time : $values['created'],
            'modified'      =>  $this->options->time,
            'commentsNum'   =>  empty($values['commentsNum']) ? 0 : intval($values['commentsNum']),
            'allowComment'  =>  !empty($values['allowComment']) && 1 == $values['allowComment'] ? 1 : 0,
			'tagsJson'      =>  empty($values['tagsJson']) ? '' : $values['tagsJson'],
            'imagesNum'     =>  empty($values['imagesNum']) ? 0 : intval($values['imagesNum']),
            'filesNum'      =>  empty($values['filesNum']) ? 0 : intval($values['filesNum']),
            'order'         =>  empty($values['order']) ? 0 : intval($values['order']),
        );

        if (!empty($values['cid'])) {
            $content['cid'] = $values['cid'];
        }
		
		/** 插件接口 */
		//HOOK $content | PLUG_Abstract_Contents_Insert($values, $this);

        /** 首先插入部分数据 */
        $insertId = $this->db->insert('table.contents')
		    ->values($content)
			->lastInsertId();
	
        if ($insertId > 0 ) {

			/** 更新缩略名 */
			$this->applyAlias(empty($values['alias']) ? $insertId : $values['alias'], $insertId);
        }
        return $insertId;
    }

    /**
     * 更新内容
     *
     * @access public
     * @param int $cid 内容cid
     * @param array $content 内容结构数组
     * @return integer
     */
    public function update($cid, array $values)
    {
        /** 构建插入结构 */
        $update = array(
			'mids'          =>  empty($values['mids']) ? '' : $values['mids'],
			'title'         =>  empty($values['title']) ? '' : htmlspecialchars($values['title']),
			'uid'           =>  isset($values['uid']) ? intval($values['uid']) : $this->user->uid,
            'type'          =>  empty($values['type']) ? 'post' : $values['type'],
            'intro'         =>  empty($values['intro']) ? '' : $values['intro'],
			'pic'           =>  empty($values['pic']) ? '' : $values['pic'],
			'template'      =>  empty($values['template']) ? '' : $values['template'],
            'text'          =>  empty($values['text']) ? '' : $this->filterText($values['text']),
            'commentsNum'   =>  empty($values['commentsNum']) ? 0 : intval($values['commentsNum']),
            'allowComment'  =>  !empty($values['allowComment']) && 1 == $values['allowComment'] ? 1 : 0,
			'tagsJson'      =>  empty($values['tagsJson']) ? '' : $values['tagsJson'],
            'imagesNum'     =>  empty($values['imagesNum']) ? 0 : intval($values['imagesNum']),
            'filesNum'      =>  empty($values['filesNum']) ? 0 : intval($values['filesNum']),
            'order'         =>  empty($values['order']) ? 0 : intval($values['order']),
        );

        $content = array();
        foreach ($values as $key => $val) {
            if (array_key_exists($key, $update)) {
                $content[$key] = $update[$key];
            }
        }

        /** 更新创建时间 */
        if (!empty($values['created'])) {
            $content['created'] = $values['created'];
        }

        $content['modified'] = $this->options->time;
		
		/** 插件接口 */
		//HOOK $content | PLUG_Abstract_Contents_Update($values, $this);
		
        $updateRows = $this->db->update('table.contents')
		    ->where('cid = ?', $cid)
		    ->values($content)
		    ->affectedRows();

		/** 更新缩略名 */
        $this->applyAlias(empty($values['alias']) ? $cid : $values['alias'], $cid);

        return $updateRows;
    }

    /**
     * 删除内容
     *
     * @access public
     * @param int $cid 内容cid
     * @return integer
     */
    public function delete($cid)
    {
		/** 插件接口 */
		//HOOK PLUG_Abstract_Contents_Delete($cid, $this);
		
		return $this->db->delete('table.contents')
		    ->where('cid = ?', $cid)
			->affectedRows();
    }

    /**
     * filterText 
     * 
     * @param mixed $text 
     * @access public
     * @return string
     */
    public function filterText($html)
    {
		/** 插件接口 */
		//HOOK {$plugged} $html | PLUG_Abstract_Contents_Filter_Text($html, $this);
		
        if (!$plugged ) {
            $html = Common::removeXSS($html);
        }
        return $html;
    }
	
    /**
     * 为内容应用缩略名
     *
     * @access public
     * @param string $alias 缩略名
     * @param mixed $cid 内容id
     * @return string
     */
    public function applyAlias($alias, $cid)
    {
		/** 插件接口 */
	    //HOOK $alias | PLUG_Abstract_Contents_Alias($alias, $this);
		
		$count = 1;
		$pass = true;
		
        /** 判断是否在数据库中已经存在 */
        while (true) {
			$row = $this->db->select('cid')
			    ->from('table.contents')
				->where('alias = ?', $alias)
				->fetchRow();
			if($row){
				if($row['cid'] != $cid){
                    $alias = $alias . '-' . $count;
                    $count ++;
			    } else {
					$pass = false;
					break;
				}
			} else {
				break;
			}
        }
		
		$pass && $this->db->update('table.contents')
		    ->where('cid = ?', $cid)
			->values(array('alias'=>$alias))
			->affectedRows();

        return $alias;
    }

    /**
     * 获取当前所有自定义模板
     *
     * @access public
     * @return array
     */
    public function getTemplates()
    {
        $files = glob($this->options->themeFile($this->options->theme, '*.php'));
        $result = array();

        foreach ($files as $file) {
            $info = Plugins::parseInfo($file);
            $file = basename($file);

            if ('index.php' != $file && 'custom' == $info['title']) {
                $result[$file] = $info['description'];
            }
        }

        return $result;
    }

    /**
     * 通用过滤器
     *
     * @access public
     * @param array $value 需要过滤的行数据
     * @return array
     * @throws Widget_Exception
     */
    public function filter(array $value)
    {
		if (isset($value['created'])) {
            $value['date'] = new Date($value['created']);

            /** 生成日期 */
            $value['year'] = $value['date']->year;
            $value['month'] = $value['date']->month;
            $value['day'] = $value['date']->day;
		}

		if (isset($value['cid'], $value['type'], $value['alias'], $value['mids'])) {		
		
            $value['category'] = NULL;
            $value['directory'] = array();
            if (!empty($value['mids'])) {
			    /** 取出第一个分类作为alias条件 */
			    $mids = explode(',', $value['mids']);
                $value['directory'] = $this->widget('Widget_Metas_Category_List')->getParentsAlias($mids[0]);
			    $value['category'] = end($value['directory']);
            }

            $tmpAlias = $value['alias'];
            $tmpCategory = $value['category'];
            $tmpDirectory = $value['directory'];
            $value['alias'] = urlencode($value['alias']);
            $value['category'] = urlencode($value['category']);
            $value['directory'] = implode('/', array_map('urlencode', $value['directory']));

            /** 获取路由类型并判断此类型在路由表中是否存在 */
		    $type = $value['type'];
            $routeExists = (NULL != Router::get($type));
		
            /** 生成静态路径 */
            $value['pathinfo'] = $routeExists ? Router::url($type, $value) : '#';

            /** 生成静态链接 */
            $value['permalink'] = Common::url($value['pathinfo'], $this->options->index);

            $value['alias'] = $tmpAlias;
            $value['category'] = $tmpCategory;
            $value['directory'] = $tmpDirectory;
		}
		
		/** 插件接口 */
		//HOOK $value | PLUG_Abstract_Contents_Filter($value, $this);
		
        return $value;
    }

    /**
     * 将每行的值压入堆栈
     *
     * @access public
     * @param array $value 每行的值
     * @return array
     */
    public function push(array $value)
    {
        $value = $this->filter($value);
        return parent::push($value);
    }

    /**
     * 输出文章发布日期
     *
     * @access public
     * @param string $format 日期格式
     */
    public function date($format = NULL)
    {
        echo $this->date->format(empty($format) ? $this->options->postDateFormat : $format);
    }

    /**
     * 输出文章内容
     *
     * @access public
     * @param mixed $more 文章截取后缀
     */
    public function content($more = false)
    {
        echo false !== $more && !empty($this->excerpt) ?
        $this->excerpt . "<p class=\"more\"><a href=\"{$this->permalink}\" title=\"{$this->title}\">{$more}</a></p>" : $this->content;
    }

    /**
     * 输出文章摘要
     *
     * @access public
     * @param integer $length 摘要截取长度
     * @param string $trim 摘要后缀
     */
    public function excerpt($length = 100, $trim = '...')
    {
        echo Common::subStr($this->intro, 0, $length, $trim);
    }

    /**
     * 输出标题
     *
     * @access public
     * @param integer $length 标题截取长度
     * @param string $trim 截取后缀
     */
    public function title($length = 0, $trim = '...')
    {
		/** 插件接口 */
	    //HOOK {$plugged} $title | PLUG_Abstract_Contents_Title($this);
		
        if (!$plugged) {
            echo $length > 0 ? Common::subStr($this->title, 0, $length, $trim) : $this->title;
        } else {
            echo $title;
        }
    }

    /**
     * 输出文章评论数
     *
     * @access public
     */
    public function commentsNum()
    {
        $args = func_get_args();
        if (!$args) {
            $args[] = '%d';
        }

        $num = intval($this->commentsNum);

        echo sprintf(isset($args[$num]) ? $args[$num] : array_pop($args), $num);
    }

    /**
     * 内容是否可以被修改
     *
     * @access public
     * @param Db_Query $condition 条件
     * @return mixed
     */
    public function isWriteable()
    {
        return $this->have() && ($this->user->pass('editor', true) || $this->uid == $this->user->uid);
    }
	
    /**
     * 获取文章权限
     *
     * @access public
     */
    public function allow($permission)
    {
        if ('edit' == $permission) {
            $allow = ($this->user->pass('editor', true) || $this->uid == $this->user->uid);
        } else {
            /** 对自动关闭反馈功能的支持 */
            if ('comment' == $permission && $this->options->commentsPostTimeout > 0 &&
            $this->options->commentsAutoClose) {
                if ($this->options->time - $this->created > $this->options->commentsPostTimeout) {
                    return false;
                }
            }
			$permission = 'allow' . ucfirst($permission);
            $allow = $this->{$permission} == 1;
        }		
        return $allow;
    }

    /**
     * 输出文章分类
     *
     * @access public
     * @param string $split 多个分类之间分隔符
     * @param boolean $link 是否输出链接
     * @param string $default 如果没有则输出
     * @return void
     */
    public function category($split = ',', $link = true, $default = NULL)
    {
	    $widgetMetas = $this->widget('Widget_Metas_Category_List');
	    $mids = explode(',', $this->mids);
        $result = array();
        foreach ($mids as $mid) {
			$category = $widgetMetas->getCategory($mid);
            $result[] = $link ? '<a href="' . $category['permalink'] . '">' . $category['name'] . '</a>' : $category['name'];
        }

        if ($result) {
			echo implode($split, $result);
        } else {
            echo $default;
        }
    }

    /**
     * 输出文章标签
     *
     * @access public
     * @param string $split 多个标签之间分隔符
     * @param boolean $link 是否输出链接
     * @param string $default 如果没有则输出
     * @return void
     */
    public function tags($split = ',', $link = true, $default = NULL)
    {
        /** 取出tags */
        if ($tags = $this->tags) {
            $result = array();
            foreach ($tags as $tag) {
                $result[] = $link ? '<a href="' . $tag['permalink'] . '">'
                . $tag['name'] . '</a>' : $tag['name'];
            }

            echo implode($split, $result);
        } else {
            echo $default;
        }
    }

    /**
     * 输出当前作者
     *
     * @access public
     * @param string $item 需要输出的项目
     * @return void
     */
    public function author($item = 'nickName')
    {
        echo $this->author->{$item};
    }
	
    protected function ___icon()
    {
		$icon = $this->pic;
		if($icon){
		    strpos($icon, '://') === FALSE && $icon = $this->options->uploadUrl . $icon;
		}else{
			$icon = $this->options->staticUrl('images/no-image.png', false);
		}
        return $icon;
    }

	// 自动生成摘要
	public function autoIntro($intro, $content) 
	{
		if(empty($intro)) {
			$intro = preg_replace('/\s{2,}/', ' ', strip_tags($content));
			if(false !== strpos($intro, '<!--more-->')){
			    list($intro) = explode('<!--more-->', $intro);
			}else{
				$intro = trim(Common::subStr($intro, 0, 255, ''));
			}
		}else{
			$intro = str_replace(array("\r\n", "\r", "\n"), '<br />', strip_tags($intro));
		}
		return $intro;
	}
}

